<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>DaoBeauty - InvokeStrategies</title>
</head>
<body bgcolor="white">
Contains the InvokeStrategies, which are used to implement functionality of the DAO interface methods.


<h3>How it works</h3>
<p/>
DaoBeauty analyses the name, the parameters and the return type of the methods declared in the DAO interface
in combination with a given <code>SessionFactory</code> and a domain class to determine, which of several strategies 
has to be used to implement the functionality of the interface method. So the functions that can be implemented 
by DaoBeaty depend on the available strategies,
which all base on the interface <code>{@link daobeauty.interceptor.invoke.InvokeStrategy}</code>.
<p/>
<h2>Available InvokeStrategy implementations</h2>
<p/>
The following implementations of <code>{@link daobeauty.interceptor.invoke.InvokeStrategy}</code> are available. 
DaoBeauty will try to fit one of this strategies to methods in the DAO interface in the order, they are listed here.
If no appropriate strategy can be determined, a <code>RuntimeException</code> will be thrown by the 
initialization method of the MethodInterceptor {@link daubeauty.interceptor.MethodInterceptor#initialize()}.
<p/>
<h3>Delegate</h3>
<p/>
When on creation of the DAO proxy any delegate objects are given, DaoBeauty will check the methods implemented
by the delegates against the methods defined in the DAO interface. If some method signatures match, all invocations of
that method will be delegated to the delegate object via the {@link daobeauty.interceptor.invoke.impl.DelegateInvoke}.<br/>
This will allow users of DaoBeauty to override any default behaviour of DaoBeauty as well as to define
complex queries that can't be generated automatically by DaoBeauty.<br/>
The delegates don't have to implement any interface. If they implement the interface {@link daobeauty.dao.SessionFactoryAware},
DaoBeauty will enshure, that his <code>SessionFactory</code> will be injected into the delegate, if it has none.
<p/>
<h3>CreateCriteria</h3>
<p/>
For a DAO inteface method with the signature <code>public {@link org.hibernate.Criteria} createCriteria()</code> 
the {@link daobeauty.interceptor.invoke.impl.CreateCriteriaInvoke} will return a Hibernate criteria
for the domain class.
<p/>
<h3>GetNamedQuery</h3>
<p/>
For a DAO inteface method with the signature <code>public {@link org.hibernate.Query} getNamedQuery(String queryName)</code>
the {@link daobeauty.interceptor.invoke.impl.GetNamedQueryInvoke} will return the Query with the given name.
For finding the named query, first a Query with the full domain class (e.g. domainClass.getName()) followed 
by a dot, followed by the name of the Query, is seached. This enshures, that a named Query "myNamedQuery"
is first searched in the scope of the hibernate mapping file for the domain class, e.g. "daobeauty.test.domain.D1.myNamedQuery".
If this named query doesn't exist, the named query is searched in the scope of the main hibernate configuration file,
e.g. "myNamedQuery". If both queries can't be found, the <code>GetNamedQueryInvoke</code> will return null.
<p/>
<h3>GetConstantObject</h3>
<p/>
For several DAO inteface methods, that just return well known objects, the {@link daobeauty.interceptor.invoke.impl.GetConstantObject}
will return that object. Concretely the method with signature <code>public {@link Class} getDomain()</code> will return 
the Class of the domain and the signature <code>public {@link java.io.Serializable} getPrimaryKey()</code> will return 
the Class of the primary key.
<p/>
<h3>CRUD</h3>
<p/>
For CRUD (Create, Read, Update, Delete) operations on the domain objects, the DAO inteface method signatures 
<code>public void save(Object domainObject)</code>,
<code>public void update(Object domainObject)</code>, <code>public void saveOrUpdate(Object domainObject)</code> and 
<code>public void delete(Object domainObject)</code> will be handled by the {@link daobeauty.interceptor.invoke.impl.CrudInvoke}.<br/>
Also same method signatures with a Collection or Array of domain objects as parameter will be handled by this strategy:<br/>
<code>public void save(Collection domainObjects)</code>,
<code>public void update(Collection domainObjects)</code>, 
<code>public void saveOrUpdate(Collection domainObjects)</code>, 
<code>public void delete(Collection domainObjects)</code>,
<code>public void save(Object[] domainObjects)</code>,
<code>public void update(Object[] domainObjects)</code>, 
<code>public void saveOrUpdate(Object[] domainObjects)</code> and 
<code>public void delete(Object[] domainObjects)</code>. In the DAO interface, the parameters should be defined for the domain class,
e.g. <code>public void save(D1 d1)</code>, <code>public void save(D1[] d1s)</code> and <code>public void save(Collection&lt;D1&gt d1s)</code>.
<p/>
<h3>NamedQueryDelegate</h3>
<p/>
For DAO interface methods having the same (case-sensitive) name as an existing named query, that named query will be invoked for
that method by the {@link daobeauty.interceptor.invoke.impl.NamedQueryDelegateInvoke}. Such methods may have also limiting, 
named and not-named parameters for the query. <i>But no {@link daobeauty.dao.Sorting} parameter.</i> For details on limiting, 
named and not-named parameters, see section <a href="#slnnnp">sorting, limiting, named and not-named parameters.</a>
<p/>
<h3>FindByExample</h3>
<p/>
For DAO interface methods with signatures <code>public Object findByExample(Object exampleDomainObject)</code> with the return type 
Object or any of the return types listed in section <a href="#rt">Return types</a> the {@link daobeauty.interceptor.invoke.impl.FindByExampleInvoke}
will apply a criteria-search with the given example object. 
<p/>
<h3>FindByPrimaryKey</h3>
<p/>
For DAO interface methods with signatures <code>public Object findByPrimaryKey(Serializable domainObjectId)</code>
and <code>public Object findById(Serializable domainObjectId)</code> with the return type 
Object (or compatible) the {@link daobeauty.interceptor.invoke.impl.FindByPrimaryKeyInvoke}
will return the domain object with the given primary key, or null if it doesn't exist. 
<p/>
<h3>FindAll</h3>
<p/>
For DAO interface methods having the name "findAll", one of the following actions is applied by the 
{@link daobeauty.interceptor.invoke.impl.FindAllInvoke}:<br/>
<dir>
	<li>If the DAO interface method has no parameters, a Criteria with the domain class 
		(like <code>FROM domainobject</code>) is executed. E.g. <code>public List&lt;D1&gt; findAll()</code></li>
	<li>If the DAO interface method has only parameters of type Limiting or/and Sorting, 
		a Criteria with the domain class (like <code>FROM domainobject</code>) 
		is executed and the limiting or/and sorting is applied. E.g. 
		<code>public List&lt;D1&gt; findAll({@link daobeauty.dao.Limiting} limiting)</code>, 
		<code>public List&lt;D1&gt; findAll({@link daobeauty.dao.Sorting} sorting)</code>, 
		<code>public List&lt;D1&gt; findAll({@link daobeauty.dao.Limiting} limiting, {@link daobeauty.dao.Sorting} sorting)</code></li>
</dir>
In all other cases the first parameter of the method must be a String that is the HQL query, which is to be executed.
Such methods may have also limiting, 
named and not-named parameters for the query. <i>But no {@link daobeauty.dao.Sorting} parameter.</i> For details on limiting, 
named and not-named parameters, see section <a href="#slnnnp">sorting, limiting, named and not-named parameters.</a>.<br/>
E. g.<br/>
<code>public List&lt;D1&gt; findAll(String hqlQuery)</code>, <code>public List&lt;D1&gt; findAll(String hqlQuery, Limiting limiting)</code>,
<code>public List&lt;D1&gt; findAll(String hqlQuery, Map&lt;String, Object&gt; namedQueryParameters)</code>,
<code>public List&lt;D1&gt; findAll(String hqlQuery, Collection queryParameters)</code>, etc.<br/>
In all cases, the return type of the method may have any return type of the ones listed in section <a href="#rt">Return types</a>.
<p/>
<h3>FindByNativeQuery</h3>
<p/>
For DAO interface methods having the name "findByNativeQuery", the 
{@link daobeauty.interceptor.invoke.impl.FindByNativeQueryInvoke} expects a String with native (SQL) query
as the first parameter.<br/>
Such methods may have also limiting, 
named and not-named parameters for the query. <i>But no {@link daobeauty.dao.Sorting} parameter.</i> For details on limiting, 
named and not-named parameters, see section <a href="#slnnnp">sorting, limiting, named and not-named parameters.</a>.<br/>
What such methods will return, depends on the query itself. A <code>select count(*) from domain</code> will return some
Integer or Long value, a <code>select name from customer where id='1'</code> will return a String,
a <code>select name from customer where id &gt; 1</code> will return a List/Array of String.
The return type handlers will try to return the type defined by the method.
E. g.<br/>
<code>public List findByNativeQuery(String sqlQuery)</code>, <code>public List findByNativeQuery(String sqlQuery, Limiting limiting)</code>,
<code>public List findByNativeQuery(String sqlQuery, Map&lt;String, Object&gt; namedQueryParameters)</code>,
<code>public List findByNativeQuery(String sqlQuery, Collection queryParameters)</code>, etc.<br/>
In all cases, the return type of the method may have any return type of the ones listed in section <a href="#rt">Return types</a>.
<p/>
<h3>FindByParsing the methodname to a criteria</h3>
<p/>
TODO
<p/>
<h3>FindCountByParsing the methodname to a criteria</h3>
<p/>
TODO
<p/>
<h3>FindCountDistinctByParsing the methodname to a criteria</h3>
<p/>
TODO
<p/>
<h3>FindExistsByParsing the methodname to a criteria</h3>
<p/>
TODO
<p/>
<h2><a name="rt">Return types</a></h2>
<p/>
Handling of return types of methods are done through two steps.
<p/> 
The first step defines, how a query will be executed through the interfaces and classes in the 
package {@link daobeauty.interceptor.returntype.executor}. 
If a DAO interface method returns a single object, then usually <code>query.setMaxResults(1).uniqueResult()</code> is invoked. If
a method returns any type of collection or array, then the query is executed with <code>query.list()</code>.
<p/>
The second step then converts the return value of the query ({@link java.util.List} or Object) to the return type of the
method via the interfaces and classes in the package {@link daobeauty.interceptor.returntype.handler}.
DaoBeauty tries to return the same type of object as defined for the method return type. Supported return types are:<br/>
<dir>
	<li>Array of domain objects, e. g. <code>public D1[] findAll();</code></li>
	<li>{@link java.util.ArrayList} of domain objects, e. g. <code>public {@link java.util.ArrayList} findAll();</code></li>
	<li>{@link java.util.LinkedList} of domain objects, e. g. <code>public {@link java.util.LinkedList} findAll();</code></li>
	<li>{@link java.util.List} of domain objects, e. g. <code>public {@link java.util.List} findAll();</code></li>
	<li>{@link java.util.Vector} of domain objects, e. g. <code>public {@link java.util.Vector} findAll();</code></li>
	<li>{@link java.util.HashSet} of domain objects, e. g. <code>public {@link java.util.HashSet} findAll();</code></li>
	<li>{@link java.util.TreeSet} of domain objects, e. g. <code>public {@link java.util.TreeSet} findAll();</code></li>
	<li>{@link java.util.SortedSet} of domain objects, e. g. <code>public {@link java.util.SortedSet} findAll();</code></li>
	<li>{@link java.util.Collection} of domain objects, e. g. <code>public {@link java.util.Collection} findAll();</code></li>
	<li>one single domain object, e. g. <code>public D1 findAll();</code></li>
	<li>{@link java.lang.Long}, e. g. <code>public {@link java.lang.Long} findCountByName(String name);</code> or <code>public long findCountByName(String name);</code></li>
	<li>{@link java.lang.Integer}, e. g. <code>public {@link java.lang.Integer} findCountByName(String name);</code> or <code>public int findCountByName(String name);</code></li>
	<li>{@link java.lang.Short}, e. g. <code>public {@link java.lang.Short} findCountByName(String name);</code> or <code>public short findCountByName(String name);</code></li>
	<li>{@link java.lang.Byte}, e. g. <code>public {@link java.lang.Byte} findCountByName(String name);</code> or <code>public byte findCountByName(String name);</code></li>
	<li>{@link java.lang.Boolean}, e. g. <code>public {@link java.lang.Boolean} findExistsByName(String name);</code> or <code>public boolean findExistsByName(String name);</code></li>
</dir>
<p/>
<h2><a name="slnnnp">Sorting, limiting, named and not-named parameters</a></h2>
<p/>
<h3>Sorting</h3>
<p/>
Sorting can be applied to several InvokeStrategies, that will internally use a {@link org.hibernate.Criteria},
e.g. FindAllInvoke with no query as parameter, FindByExampleInvoke and FindByParsingInvoke.
For this purpose DaoBeauty will check the DAO interface method signature for a parameter of type {@link daobeauty.dao.Sorting}
which defines the sorting, e.g. <code>public List&lt;D1&gt; findAll({@link daobeauty.dao.Sorting} sorting)</code>. Since there is no possibility to apply sorting on named queries or user given HQL / SQL queries,
methods using such queries can not contain a sorting parameter. But a sorting can be defined in the query itself.
<p/>
<h3>Limiting</h3>
<p/>
Limiting (e.g. maxResults and firstResultOffset) can be applied to all InvokeStrategies, that internally will 
use some kind of query. Namely: FindByExampleInvoke, FindAllInvoke, FindByParsingInvoke, 
FindByNativeQueryInvoke, NamedQueryDelegateInvoke.<br/>
For this purpose DaoBeauty will check the DAO interface method signature for a parameter of type {@link daobeauty.dao.Limiting}
which defines the limiting, e.g. <code>public List&lt;D1&gt; findAll({@link daobeauty.dao.Limiting} limiting)</code>.
<p/>
<h3>Named query parameters</h3>
<p/>
InvokeStrategies that internally use HQL or SQL queries, such as NamedQueryDelegateInvoke, FindAllInvoke with a HQL query parameter and FindByNativQueryInvoke,
can use named parameters for their queries. Named parameters have to be given as a {@link java.util.Map} with the key
beeing a String, the name of the named parameter, and an Object as the value.<br/>
DaoBeauty will check the DAO interface method signature of such methods for a Map parameter. E.g.
<code>public List&lt;D1&gt; findAll(String hqlQuery, Map&lt;String, Object&gt; namedQueryParameters)</code> will be interpreted as a HQL query
with named parameters. It's important, that except a Limiting parameter, there will be no other parameters on the method signature.
So <code>public List&lt;D1&gt; findAll(String hqlQuery, Map&lt;String, Object&gt; namedQueryParameters)</code> and
<code>public List&lt;D1&gt; findAll(String hqlQuery, Map&lt;String, Object&gt; namedQueryParameters, Limiting limiting)</code>
are valid signatures, but <code>public List&lt;D1&gt; findAll(String hqlQuery, Map&lt;String, Object&gt; namedParameters, Object anotherObject)</code>
is not valid.<br/>
The combination of named query parameters and Limiting is ok. There may be <b>no</b> mixing of named and not-named query parameters.
The first String parameter of the method will always be interpreted as the query itself for the FindAllInvoke and FindByNativQueryInvoke.
<p/>
The filling of queries with parameters is done via the classes and interfaces located in the package {@link daobeauty.interceptor.invoke.fill}.
<p/>
<h3>Not-named query parameters</h3>
<p/>
InvokeStrategies that internally use HQL or SQL queries, such as NamedQueryDelegateInvoke, FindAllInvoke with a HQL query parameter and FindByNativQueryInvoke,
can use not-parameters for their queries.<br/>
Non-named query parameters will be detected for DAO interface methods by DaoBeauty in several cases:<br/>
<dir>
	<li>The method can have an array of objects as query parameters, e.g. <code>public List&lt;D1&gt; findAll(String hqlQuery, Object[] queryParameters)</code></li>
	<li>The method can have any {@link java.util.Collection} of objects as query parameters, e.g. <code>public List&lt;D1&gt; findAll(String hqlQuery, {@link java.util.Collection} queryParameters)</code></li>
	<li>The method can have any amount of object parameters as query parameters, e.g. <code>public List&lt;D1&gt; findAll(String hqlQuery, Object queryParameter1, Object queryParameter2, ...)</code></li>
</dir>
The combination of not-named query parameters and Limiting is ok. There may be <b>no</b> mixing of named and not-named query parameters. 
The first String parameter of the method will always be interpreted as the query itself for the FindAllInvoke and FindByNativQueryInvoke.
<p/>
The filling of queries with parameters is done via the classes and interfaces located in the package {@link daobeauty.interceptor.invoke.fill}.
<p/>
@see daubeauty.interceptor.MethodInterceptor
@see daobeauty.interceptor.invoke.InvokeStrategy
@see daobeauty.interceptor.invoke.impl.DelegateInvoke
@see daobeauty.interceptor.invoke.impl.CreateCriteriaInvoke
@see daobeauty.interceptor.invoke.impl.GetNamedQueryInvoke
@see daobeauty.interceptor.invoke.impl.GetConstantObjectInvoke
@see daobeauty.interceptor.invoke.impl.CrudInvoke
@see daobeauty.interceptor.invoke.impl.NamedQueryDelegateInvoke
@see daobeauty.interceptor.invoke.impl.FindByPrimaryKeyInvoke
@see daobeauty.interceptor.invoke.impl.FindByExampleInvoke
@see daobeauty.interceptor.invoke.impl.FindAllInvoke
@see daobeauty.interceptor.invoke.impl.FindByNativeQueryInvoke
@see daobeauty.interceptor.invoke.impl.FindByParsingInvoke
@see daobeauty.interceptor.invoke.fill
@see daobeauty.interceptor.invoke.crud
@see daobeauty.interceptor.invoke.parser
@see daobeauty.dao.Limiting
@see daobeauty.dao.Sorting
@see daobeauty.dao.SessionFactoryAware
</body>
</html>
